#include "table_state.h"

namespace Tetris{

Table_State::Table_State(Table* p_d,Shape* p_s){
	this->p_data = p_d;
	this->p_shape = p_s;
	this->top = - this->p_shape->GetMinY() ;
	this->left = (Table::COL - this->p_shape->Column()) / 2;
	if(this->ShpeValid()){
		this->setShapeToTable(this->p_shape->ColorStyle());
		this->initialShapeValid = true;
	}
	else
		this->initialShapeValid = false;
}
bool Table_State::CanGenerateShape() const{
	return this->initialShapeValid;
}
bool Table_State::MoveBottom(){
	while(this->MoveDown());
	return true;
}

bool Table_State::MoveDown(){
	bool ret = true;
	this->setShapeToTable(0);
	++ this->top;
	if(!this->ShpeValid()){
		-- this->top;
		ret = false;
	}
	this->setShapeToTable(this->p_shape->ColorStyle());
	return ret;
}

bool Table_State::MoveLeft(){
	bool ret = true;
	this->setShapeToTable(0);
	-- this->left;
	if(!this->ShpeValid()){
		++ this->left;
		ret = false;
	}
	this->setShapeToTable(this->p_shape->ColorStyle());
	return ret;
}

bool Table_State::MoveRight(){
	bool ret = true;
	this->setShapeToTable(0);
	++ this->left;
	if(!this->ShpeValid()){
		-- this->left;
		ret = false;
	}
	this->setShapeToTable(this->p_shape->ColorStyle());
	return ret;
}

bool Table_State::ShapeCanTransform() const {
	Shape* p = this->p_shape;
	Shape* p2 = p->Clone();
	p->Transform();
	bool re = this->ShpeValid();
	p->Restore(p2);
	delete p2;
	return re;
}

bool Table_State::ShpeValid() const {
	int rightBound = this->p_data->COL - 1;
	int downBound = this->p_data->ROW - 1;
	for(int i=0;i<this->p_shape->Row();++i)	{
		for(int j=0;j<this->p_shape->Column();++j) {
			if(this->p_shape->GetValue(j,i)){
				int x = this->left + j;
				int y = this->top + i;
				if(x < 0 || x > rightBound || y > downBound || y < 0)
					return false;
				if(this->p_data->GetVal(x,y))
					return false;
			}
		}
	}
	return true;
}

void Table_State::setShapeToTable(unsigned char val){
	for(int i=0;i<this->p_shape->Row();++i)	{
		int y = this->top + i;
		if(y < 0 || y >= Table::ROW) continue;
		for(int j=0;j<this->p_shape->Column();++j) {
			int x = this->left + j;
			if(x < 0 || x >= Table::COL) continue;
			if(this->p_shape->GetValue(j,i)){
				this->p_data->SetVal(x,y,val);
			}
		}
	}
}

int Table_State::UpdateTable(){
	int score = 0;
	for(int i=0;i<this->p_shape->Row();++i)	{
		bool flag = true;
		for(int k = 0; k < this->p_data->COL; ++k){
			if(!this->p_data->GetVal(k,this->top + i)){
				flag = false;
				break;
			}
		}
		if(flag){
			++ score;
			for(int m=this->top + i - 1; m >= 0; --m){
				for(int k = 0; k < this->p_data->COL; ++k){
					this->p_data->SetVal(k,m+1,this->p_data->GetVal(k,m));
				}
			}
		}
	}
	return score;
}

bool Table_State::Transform(){
	bool ret = false;
	this->setShapeToTable(0);
	if(this->ShapeCanTransform()){
		this->p_shape->Transform();
		ret = true;
	}
	this->setShapeToTable(this->p_shape->ColorStyle());
}

const Table* Table_State::GetTable() const{
	return this->p_data;
}
const Shape* Table_State::GetShape() const{
	return this->p_shape;
}


}